package com.seanLab.tool.TagSuggestModel.ExpandRank;

import com.seanLab.dto.SuggestModelArticleDto;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.thunlp.matrix.NormalMatrix;
import org.thunlp.matrix.pagerank.PageRank;
import org.thunlp.misc.Counter;
import org.thunlp.misc.WeightString;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

/**
 * 调整核心模型使ExpandRank退化为TextRank
 */
public class FakeExpandRankKE extends ExpandRankKE{
    private static Logger LOG = Logger.getLogger(FakeExpandRankKE.class.getName());
    public void loadModel(String modelPath) throws IOException {
        LOG.info("fake expand rank load nothing!");
    }

    public double adjustRank(String word, double score) {
        return score;
    }

    public List<WeightString> suggest(SuggestModelArticleDto p) {
        String content = p.getContent();
        content = extractor.clean(content);
//        // fake
//        List<WeightString> keywords = extractKeywords(content);
//        Query q;
//        try {
//            q = makeQueryFromKeywords(keywords, numKeywords);
//        } catch (ParseException e1) {
//            LOG.warning("Cannot make query from " + p.getTitle());
//            return EMPTY_SUGGESTION;
//        }
//        TopDocs topDocs;
//        try {
////            topDocs = docsSearcher.search(q, null, k); //For lucene 2.0
//            topDocs = docsSearcher.search(q, k); //For lucene 6.6
//        } catch (IOException e1) {
//            LOG.warning("IOException when search for " + p.getTitle());
//            return EMPTY_SUGGESTION;
//        }

        String[] words = extractor.getWords(content);
        Counter<String> termFreq = new Counter<String>();

        // calculate the word tf
        HashMap<String, Integer> textMap = new HashMap<String, Integer>();
        Vector<Integer> textWordId = new Vector<Integer>();
        int num = 0;

        for (String word : words) {
            termFreq.inc(word, 1);
            if (!textMap.containsKey(word)) {
                textMap.put(word, num);
                textWordId.add(num);
                num++;
            } else {
                textWordId.add(textMap.get(word));
            }
        }

//        // fake
//        // Collect tags.
//        //Map<String, Double> tags = new Hashtable<String, Double>();
//        Vector<Vector<Integer>> otherTexts = new Vector<Vector<Integer>>();
//        Vector<Double> scores = new Vector<Double>();
//        for (int i = 0; i < topDocs.scoreDocs.length; i++) {
//            int resultId = topDocs.scoreDocs[i].doc;
//            double score = topDocs.scoreDocs[i].score;
//            Document doc;
//            try {
//                doc = docsSearcher.doc(resultId);
//            } catch (CorruptIndexException e1) {
//                LOG.warning("Corrupted index when searching for " + p.getTitle());
//                return EMPTY_SUGGESTION;
//            } catch (IOException e1) {
//                LOG.warning("IOException when looking up doc " + p.getTitle());
//                return EMPTY_SUGGESTION;
//            }
//
//            String[] otherWords = extractor.getWords(doc.get("content"));
//            Vector<Integer> otherText = new Vector<Integer>();
//            for (String word : otherWords) {
//                if (!textMap.containsKey(word)) {
//                    textMap.put(word, num);
//                    otherText.add(num);
//                    num++;
//                } else {
//                    otherText.add(textMap.get(word));
//                }
//            }
//            otherTexts.add(otherText);
//            scores.add(score);
//
//			/*
//			String[] docTags = doc.get("tags").split(" ");
//			for (String tagStr : docTags) {
//				Double weight = tags.get(tagStr);
//				if (weight == null) {
//					weight = 0.0;
//				}
//				tags.put(tagStr, weight + score);
//			}
//			*/
//        }

        NormalMatrix matrix = new NormalMatrix(num, num);
        int window = 10;
        int len = textWordId.size();
        if (len < window) {
            for (int i = 1; i < len; i++) {
                addEdge(matrix, textWordId, 0, i);
            }
            for (int i = 1; i < len - 1; i++) {
                addEdge(matrix, textWordId, i, len - 1);
            }
        } else {
            for (int i = 1; i < window - 1; i++) {
                addEdge(matrix, textWordId, 0, i);
            }
            for (int i = 0; i <= len - window; i++) {
                addEdge(matrix, textWordId, i, i + window - 1);
            }
            for (int i = len - window + 1; i < len - 1; i++) {
                addEdge(matrix, textWordId, i, len - 1);
            }
        }

//        // fake
//        for(int j = 0; j < otherTexts.size(); j ++){
//            len = otherTexts.get(j).size();
//            double score = scores.get(j);
//            if (len < window) {
//                for (int i = 1; i < len; i++) {
//                    addEdge(matrix, otherTexts.get(j), 0, i, score);
//                }
//                for (int i = 1; i < len - 1; i++) {
//                    addEdge(matrix, otherTexts.get(j), i, len - 1, score);
//                }
//            } else {
//                for (int i = 1; i < window - 1; i++) {
//                    addEdge(matrix, otherTexts.get(j), 0, i, score);
//                }
//                for (int i = 0; i <= len - window; i++) {
//                    addEdge(matrix, otherTexts.get(j), i, i + window - 1, score);
//                }
//                for (int i = len - window + 1; i < len - 1; i++) {
//                    addEdge(matrix, otherTexts.get(j), i, len - 1, score);
//                }
//            }
//        }

        PageRank.prepareMatrix(matrix);
        double rankValue[] = PageRank.pageRank(matrix, 100);

        Iterator<Map.Entry<String, Long>> iter = termFreq.iterator();
        List<WeightString> suggested = new ArrayList<WeightString>();
        while (iter.hasNext()) {
            Map.Entry<String, Long> e = iter.next();
            String word = e.getKey();
            int textId = textMap.get(word);
            double rank = rankValue[textId];
            // use idf to adjust rank in IDFTextRank
            rank = adjustRank(word, rank);
            suggested.add(new WeightString(word, rank));
        }

        // Weight tags.
        Collections.sort(suggested, new Comparator<WeightString>() {
            public int compare(WeightString o1, WeightString o2) {
                return Double.compare(o2.weight, o1.weight);
            }

        });

//        double normalTf = 0.0;
//        Vector<Double> record = new Vector<Double>();
//        for(int i = 0; i < suggested.size() && i < 2; i ++){
//            String keyword = suggested.get(i).text;
//            long tf = termFreq.get(keyword);
//            if(tf != 0l && p.getTags().contains(keyword)){
//                normalTf = (double) tf / (double) words.length;
//                normalTf = (int)(normalTf * 1000) / 1000.0;
//                record.add(normalTf);
//            }
//        }
//        suggestTf.add(record);
//
//        Vector<Double> recordAnswer = new Vector<Double>();
//        for(String keyword : p.getTags()){
//            long tf = termFreq.get(keyword);
//            if(tf != 0l){
//                normalTf = (double) tf / (double) words.length;
//                normalTf = (int)(normalTf * 1000) / 1000.0;
//                recordAnswer.add(normalTf);
//            }
//        }
//        answerTf.add(recordAnswer);

        return suggested;
    }

}
